home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / os / sprite.X11R3 / RCS / tcp.c,v < prev    next >
Encoding:
Text File  |  1989-10-26  |  26.6 KB  |  1,100 lines

  1. head     1.7;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.7
  10. date     89.08.15.21.34.45;  author ouster;  state Exp;
  11. branches ;
  12. next     1.6;
  13.  
  14. 1.6
  15. date     88.09.09.18.00.16;  author ouster;  state Exp;
  16. branches ;
  17. next     1.5;
  18.  
  19. 1.5
  20. date     88.09.09.09.00.04;  author ouster;  state Exp;
  21. branches ;
  22. next     1.4;
  23.  
  24. 1.4
  25. date     88.09.08.18.15.45;  author ouster;  state Exp;
  26. branches ;
  27. next     1.3;
  28.  
  29. 1.3
  30. date     87.11.29.19.50.57;  author deboor;  state Exp;
  31. branches ;
  32. next     1.2;
  33.  
  34. 1.2
  35. date     87.11.01.20.40.52;  author deboor;  state Exp;
  36. branches ;
  37. next     1.1;
  38.  
  39. 1.1
  40. date     87.11.01.20.23.36;  author deboor;  state Exp;
  41. branches ;
  42. next     ;
  43.  
  44.  
  45. desc
  46. @Functions to support TCP connections
  47. @
  48.  
  49.  
  50. 1.7
  51. log
  52. @Fixed to use htons instead of htonl:  little-endian machines
  53. end up losing the port number.
  54. @
  55. text
  56. @/*-
  57.  * tcp.c --
  58.  *    Functions to communicate with clients over a TCP connection.
  59.  *
  60.  * Copyright (c) 1987 by the Regents of the University of California
  61.  *
  62.  * Permission to use, copy, modify, and distribute this
  63.  * software and its documentation for any purpose and without
  64.  * fee is hereby granted, provided that the above copyright
  65.  * notice appear in all copies.  The University of California
  66.  * makes no representations about the suitability of this
  67.  * software for any purpose.  It is provided "as is" without
  68.  * express or implied warranty.
  69.  *
  70.  *
  71.  */
  72. #ifndef lint
  73. static char rcsid[] =
  74. "$Header: /b/X/src/cmds/Xsprite/os/RCS/tcp.c,v 1.6 88/09/09 18:00:16 ouster Exp Locker: ouster $ SPRITE (Berkeley)";
  75. #endif lint
  76.  
  77. #ifdef TCPCONN
  78.  
  79. /*
  80.  * The following includes must be first, or the file won't compile.
  81.  */
  82.  
  83. #define Time SpriteTime
  84. #include    <fs.h>
  85. #undef Time
  86. #include    <stdlib.h>
  87.  
  88. #include    "spriteos.h"
  89. #include    "Xproto.h"
  90. #include    "opaque.h"
  91.  
  92. #include    <bit.h>
  93. #include    <errno.h>
  94. #include    <signal.h>
  95. #include    <sys/types.h>
  96. #include    <sys/socket.h>
  97. #include    <sys/time.h>
  98. #include    <netinet/in.h>
  99.  
  100. int    TCP_Conn;     /* Passive socket for listening */
  101.  
  102. typedef struct {
  103.     int              streamID;     /* Active socket for client */
  104.     ClientPtr      client;       /* Back pointer to Client descriptor */
  105.     Address       buffer;       /* Input buffer */
  106.     Address       bufPtr;       /* Current position in buffer */
  107.     int              numBytes;     /* Bytes remaining in buffer */
  108.     int          needData;     /* 1 if need to read data */
  109. } TCPPrivRec, *TCPPrivPtr;
  110.  
  111. typedef enum {
  112.     TCP_READ, TCP_WRITE
  113. } IoOperation;
  114.  
  115. /*
  116.  * REASONABLE_TIME is the amount of time we'll wait for a client connection
  117.  * to unblock, while MAX_BLOCK is the number of times we'll let the connection
  118.  * block us before aborting the whole shebang.
  119.  */
  120. #define REASONABLE_TIME        4
  121. #define MAX_BLOCK         2
  122.  
  123. static void TCPCloseClient();
  124. static char *TCPReadClient();
  125. static int  TCPWriteClient();
  126.  
  127. /*-
  128.  *-----------------------------------------------------------------------
  129.  *
  130.  * TCP_Init --
  131.  *    Initialize the TCP module by creating the passive socket and
  132.  *    storing its stream ID in TCP_Conn.
  133.  *
  134.  * Results:
  135.  *    None.
  136.  *
  137.  * Side Effects:
  138.  *    A passive socket is opened and its streamID placed in TCP_Conn.
  139.  *
  140.  *-----------------------------------------------------------------------
  141.  */
  142. void
  143. TCP_Init()
  144. {
  145.     struct sockaddr_in    inAddr;
  146.     int                  displayNum;
  147.     struct sigvec      ignore;
  148.  
  149.     displayNum = atoi(display);
  150.     inAddr.sin_port = htons(X_TCP_PORT + displayNum);
  151.     inAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  152.  
  153.     TCP_Conn = socket(AF_INET, SOCK_STREAM, 0);
  154.     if (TCP_Conn < 0) {
  155.     Error("Creating TCP socket");
  156.     FatalError("Couldn't create TCP socket...\n");
  157.     /*NOTREACHED*/
  158.     }
  159.     if (bind(TCP_Conn, (struct sockaddr *) &inAddr, sizeof(inAddr)) < 0) {
  160.     Error("Binding TCP socket");
  161.     FatalError("Couldn't bind TCP socket...\n");
  162.     /*NOTREACHED*/
  163.     }
  164.     if (listen(TCP_Conn, 5) < 0) {
  165.     Error("listen(TCP_Conn)");
  166.     FatalError("Couldn't listen on TCP socket...\n");
  167.     /*NOTREACHED*/
  168.     }
  169.     (void)Ioc_SetBits(TCP_Conn, IOC_NON_BLOCKING);
  170.     ignore.sv_handler = SIG_IGN;
  171.     ignore.sv_mask = ignore.sv_onstack = 0;
  172.     sigvec(SIGPIPE, &ignore, (struct sigvec *) 0);
  173. }
  174.  
  175. /*-
  176.  *-----------------------------------------------------------------------
  177.  *
  178.  * TCPConnIO --
  179.  *    Perform some I/O on a tcp connection with timeouts.
  180.  *
  181.  * Results:
  182.  *    Zero is returned if the operation completed successfully,
  183.  *    a non-zero errno otherwise.
  184.  *
  185.  * Side Effects:
  186.  *    The data are transmitted or received.
  187.  *
  188.  *-----------------------------------------------------------------------
  189.  */
  190. static ReturnStatus
  191. TCPConnIO(streamID, numBytes, bufPtr, ioType)
  192.     int              streamID;
  193.     int              numBytes;
  194.     Address       bufPtr;
  195.     IoOperation      ioType;
  196. {
  197.     struct timeval      timeout;
  198.     int                  *selMask;
  199.     int                  numIO;
  200.     int                  timesBlocked;
  201.  
  202.     Bit_Alloc(streamID+1, selMask);
  203.     timesBlocked = 0;
  204.     while (1) {
  205.     if (ioType == TCP_WRITE) {
  206.         numIO = write(streamID, bufPtr, numBytes);
  207.     } else {
  208.         numIO = read(streamID, bufPtr, numBytes);
  209.     }
  210.     if (numIO != -1) {
  211.         /*
  212.          * I/O was successful, but it might have been short. Subtract
  213.          * the number of bytes dealt with from that we have to handle
  214.          * and if it's zero, we've finished successfully. Else keep
  215.          * going.
  216.          */
  217.         numBytes -= numIO;
  218.         bufPtr += numIO;
  219.         if (numBytes == 0) {
  220.         Bit_Free(selMask);
  221.         return (0);
  222.         }
  223.     } else if (errno == EWOULDBLOCK) {
  224.         /*
  225.          * The operation blocked. We only allow the client to block us
  226.          * a certain number of times before we return an error. If we're
  227.          * still being patient, we select on the stream for a reasonable
  228.          * time and loop once it's ready or the time has expired.
  229.          */
  230.         timesBlocked += 1;
  231.         if (timesBlocked > MAX_BLOCK) {
  232.         Bit_Free(selMask);
  233.         return (EWOULDBLOCK);
  234.         }
  235.  
  236.         timeout.tv_sec = REASONABLE_TIME;
  237.         timeout.tv_usec = 0;
  238.         do {
  239.         Bit_Set(streamID, selMask);
  240.         numIO = select(streamID+1, 
  241.                (ioType == TCP_READ ? selMask : (int *) 0),
  242.                (ioType == TCP_WRITE ? selMask : (int *) 0),
  243.                (int *) 0, &timeout);
  244.         } while (errno == EINTR);
  245.     } else {
  246.         /*
  247.          * Some other error occurred. Abort and return it.
  248.          */
  249.         Bit_Free(selMask);
  250.         return (errno);
  251.     }
  252.     }
  253. }
  254.  
  255. /*-
  256.  *-----------------------------------------------------------------------
  257.  *
  258.  * TCPClientAuthorized --
  259.  *    See if a client that is connecting over TCP is authorized to do
  260.  *    so.
  261.  *
  262.  * Results:
  263.  *    1 if the connection is OK. 0 otherwise.
  264.  *
  265.  * Side Effects:
  266.  *    *pSwapped is set 1 if the client needs to be byte-swapped.
  267.  *    *pReason points to a reason for the refusal, if such there be.
  268.  *
  269.  *-----------------------------------------------------------------------
  270.  */
  271. static int
  272. TCPClientAuthorized(conn, pSwapped, pInAddr, pReason)
  273.     int                  conn;          /* StreamID of connection */
  274.     Bool              *pSwapped;  /* OUT: True if client is byte-swapped */
  275.     struct sockaddr    *pInAddr;   /* Address of connected client */
  276.     char              **pReason;  /* OUT: Reason for refusal */
  277. {
  278.     xConnClientPrefix    xccp;        /* Prefix of info from client */
  279.     
  280.     *pReason = (char *)NULL;
  281.     
  282.     if (TCPConnIO(conn, sizeof(xccp), &xccp, TCP_READ) != 0) {
  283.     if (DBG(TCP)) {
  284.         Error("Reading client prefix");
  285.     }
  286.     *pReason = "Couldn't read client prefix";
  287.     return (0);
  288.     }
  289.     if (xccp.byteOrder != whichByteIsFirst) {
  290.     SwapConnClientPrefix(&xccp);
  291.     *pSwapped = 1;
  292.     } else {
  293.     *pSwapped = 0;
  294.     }
  295.  
  296.     if ((xccp.majorVersion != X_PROTOCOL) ||
  297.     (xccp.minorVersion != X_PROTOCOL_REVISION)) {
  298.         *pReason = "Protocol version mismatch";
  299.         return (0);
  300.     }
  301.  
  302.     if (InvalidHost(FamilyInternet, pInAddr)) {
  303.     *pReason = "Permission denied";
  304.     return (0);
  305.     }
  306.     if (xccp.nbytesAuthProto != 0) {
  307.     char *authProto;
  308.  
  309.     authProto = (char *)ALLOCATE_LOCAL(xccp.nbytesAuthProto);
  310.     if (TCPConnIO(conn, xccp.nbytesAuthProto, authProto,
  311.               TCP_READ) != 0) {
  312.             *pReason = "Couldn't read authorization protocol string";
  313.             DEALLOCATE_LOCAL(authProto);
  314.             return (0);
  315.     }
  316.     DEALLOCATE_LOCAL(authProto);
  317.     }
  318.     if (xccp.nbytesAuthString != 0) {
  319.     char *authString;
  320.  
  321.     authString = (char *)ALLOCATE_LOCAL(xccp.nbytesAuthString);
  322.     if (TCPConnIO(conn, xccp.nbytesAuthString, authString,
  323.               TCP_READ) != 0) {
  324.                 *pReason = "Couldn't read authorization string";
  325.                 DEALLOCATE_LOCAL(authString);
  326.                 return (0);
  327.     }
  328.     DEALLOCATE_LOCAL(authString);
  329.     }
  330.     return (1);
  331. }
  332.  
  333. /*-
  334.  *-----------------------------------------------------------------------
  335.  *
  336.  * TCPConnFail --
  337.  *    Report connection failure to the client.
  338.  *
  339.  * Results:
  340.  *    None.
  341.  *
  342.  * Side Effects:
  343.  *    An xConnSetupPrefix is sent.
  344.  *
  345.  *-----------------------------------------------------------------------
  346.  */
  347. static void
  348. TCPConnFail(streamID, swapped, reason)
  349.     int        streamID;
  350.     Bool    swapped;
  351.     char    *reason;
  352. {
  353.     xConnSetupPrefix *packet;
  354.     int        reasonLength;
  355.     int        totalLength;
  356.     int        numWritten;
  357.  
  358.     reasonLength = strlen(reason);
  359.     totalLength = (reasonLength + 3) >> 2;
  360.     
  361.     numWritten = sizeof(xConnSetupPrefix) + (totalLength << 2);
  362.     packet = (xConnSetupPrefix *)ALLOCATE_LOCAL(numWritten);
  363.  
  364.     packet->success = xFalse;
  365.     packet->lengthReason = reasonLength;
  366.     packet->length = totalLength;
  367.     if (!swapped) {
  368.     packet->majorVersion = X_PROTOCOL;
  369.     packet->minorVersion = X_PROTOCOL_REVISION;
  370.     } else {
  371.     short      n;
  372.  
  373.     swaps(&packet->length, n);
  374.     packet->majorVersion = lswaps(X_PROTOCOL);
  375.     packet->minorVersion = lswaps(X_PROTOCOL_REVISION);
  376.     }
  377.     strcpy ((char *)(packet+1), reason);
  378.     (void)TCPConnIO(streamID, numWritten, packet, TCP_WRITE);
  379.     DEALLOCATE_LOCAL(packet);
  380. }
  381.  
  382. /*-
  383.  *-----------------------------------------------------------------------
  384.  *
  385.  * TCP_EstablishNewConnections --
  386.  *    A connection has been discovered on the passive TCP socket, so
  387.  *    we accept it and do all the things we're supposed to do...
  388.  *
  389.  *    XXX: Only accept one new connection, should we accept more?
  390.  *
  391.  * Results:
  392.  *    None.
  393.  *
  394.  * Side Effects:
  395.  *    A new ClientPtr is placed in the passed array and the number of
  396.  *    new clients is incremented.
  397.  *
  398.  *-----------------------------------------------------------------------
  399.  */
  400. void
  401. TCP_EstablishNewConnections(pNewClients, pNumNew)
  402.     ClientPtr          *pNewClients;
  403.     int                  *pNumNew;
  404. {
  405.     int                  newID;        /* New client stream */
  406.     ClientPtr          client;        /* New client record */
  407.     struct sockaddr    inAddr;        /* Address of new client */
  408.     int                  addrLen;    /* Length of new client's address */
  409.     int           swapped;    /* 1 if client is byte-swapped */
  410.     ClntPrivPtr          pPriv;        /* OS-global private data for client */
  411.     TCPPrivPtr          ptcpPriv;   /* Our private data */
  412.     char              *reason;    /* Reason for connection refusal */
  413.     
  414.     pNewClients += *pNumNew;
  415.  
  416.     addrLen = sizeof(inAddr);
  417.     newID = accept(TCP_Conn, &inAddr, &addrLen);
  418.     if (newID < 0) {
  419.     if (DBG(TCP)) {
  420.         Error("accept");
  421.     }
  422.     return;
  423.     }
  424.     if (!TCPClientAuthorized(newID, &swapped, &inAddr, &reason)) {
  425.     if (DBG(TCP)) {
  426.         ErrorF("Unauthorized connection\n");
  427.     }
  428.     TCPConnFail(newID, swapped, reason);
  429.     close(newID);
  430.     return;
  431.     }
  432.     client = (ClientPtr) NextAvailableClient();
  433.     if (client == NullClient) {
  434.     if (DBG(TCP)) {
  435.         ErrorF("No more clients!\n");
  436.     }
  437.     TCPConnFail(newID, swapped, "No more client slots");
  438.     close(newID);
  439.     return;
  440.     }
  441.     pPriv = (ClntPrivPtr) malloc(sizeof(ClntPrivRec));
  442.     pPriv->readProc = TCPReadClient;
  443.     pPriv->writeProc = TCPWriteClient;
  444.     pPriv->closeProc = TCPCloseClient;
  445.     pPriv->ready = pPriv->mask = (int *)0;
  446.     pPriv->maskWidth = 0;
  447.     
  448.     ptcpPriv = (TCPPrivPtr) malloc(sizeof(TCPPrivRec));
  449.     pPriv->devicePrivate = (pointer)ptcpPriv;
  450.     
  451.     client->osPrivate = (pointer)pPriv;
  452.     client->swapped = swapped;
  453.     
  454.     ptcpPriv->streamID = newID;
  455.     ptcpPriv->client = client;
  456.     ptcpPriv->buffer = (Address)NULL;
  457.     ptcpPriv->numBytes = 0;
  458.     ptcpPriv->needData = 1;
  459.     
  460.     ExpandMasks(pPriv, newID);
  461.     
  462.     Ioc_SetBits(newID, IOC_NON_BLOCKING);
  463.     
  464.     if (GrabDone) {
  465.     Bit_Set(newID, SavedAllClientsMask);
  466.     Bit_Set(newID, SavedAllStreamsMask);
  467.     } else {
  468.     Bit_Set(newID, AllClientsMask);
  469.     Bit_Set(newID, AllStreamsMask);
  470.     }
  471.     if (DBG(TCP) || DBG(CONN)) {
  472.     ErrorF("New TCP connection: client %d (newID = %d)\n", client->index,
  473.            newID);
  474.     }
  475.     *pNewClients = client;
  476.     pNewClients++;
  477.     (*pNumNew)++;
  478. }
  479.  
  480. /*-
  481.  *-----------------------------------------------------------------------
  482.  *
  483.  * TCPCloseClient --
  484.  *    Close down a client we're handling and free up our part of the
  485.  *    resources.
  486.  *
  487.  * Results:
  488.  *    None.
  489.  *
  490.  * Side Effects:
  491.  *    The active stream to the client is closed and the private data
  492.  *    freed. The stream is removed from these masks: 
  493.  *        AllStreamsMask, SavedAllStreamsMask, AllClientsMask,
  494.  *        SavedAllClientsMask, ClientsWithInputMask
  495.  *
  496.  *-----------------------------------------------------------------------
  497.  */
  498. static void
  499. TCPCloseClient(pPriv)
  500.     ClntPrivPtr      pPriv;        /* Private data for client to be closed */
  501. {
  502.     TCPPrivPtr      ptcpPriv;
  503.  
  504.     ptcpPriv = (TCPPrivPtr)pPriv->devicePrivate;
  505.  
  506.     if (ptcpPriv->buffer) {
  507.     free((char *) ptcpPriv->buffer);
  508.     }
  509.     Bit_Clear(ptcpPriv->streamID, ClientsWithInputMask);
  510.  
  511.     if (GrabDone) {
  512.     Bit_Clear(ptcpPriv->streamID, SavedAllClientsMask);
  513.     Bit_Clear(ptcpPriv->streamID, SavedAllStreamsMask);
  514.     if (grabbingClient == ptcpPriv->client) {
  515.         Bit_Clear(ptcpPriv->streamID, AllClientsMask);
  516.         Bit_Clear(ptcpPriv->streamID, AllStreamsMask);
  517.     }
  518.     } else {
  519.     Bit_Clear(ptcpPriv->streamID, AllClientsMask);
  520.     Bit_Clear(ptcpPriv->streamID, AllStreamsMask);
  521.     }
  522.     free((char *)ptcpPriv);
  523. }
  524.  
  525. #define request_length(req, cli) \
  526.      (((cli)->swapped?lswaps(((xReq *)(req))->length):\
  527.       ((xReq *)(req))->length) << 2)
  528. /*-
  529.  *-----------------------------------------------------------------------
  530.  *
  531.  * TCPReadClient --
  532.  *    Read a request from the given client.
  533.  *
  534.  * Results:
  535.  *    Pointer to the start of the request.
  536.  *
  537.  * Side Effects:
  538.  *    Data may be read from the client's connection.
  539.  *
  540.  *-----------------------------------------------------------------------
  541.  */
  542. /*ARGSUSED*/
  543. static char *
  544. TCPReadClient(pPriv, pStatus, oldbuf)
  545.     ClntPrivPtr      pPriv;        /* Client with input */
  546.     int              *pStatus;     /* Result of read:
  547.                  *  >0 -- number of bytes in request
  548.                  *   0 -- not all the request is there
  549.                  *  <0 -- error */
  550.     char          *oldbuf;      /* Previous buffer */
  551. {
  552.     xReq          *reqPtr;      /* Request being returned */
  553.     int              numRead;      /* Number of bytes read from the socket */
  554.     int              need;            /* Number of bytes needed */
  555.     TCPPrivPtr      ptcpPriv;     /* Our private data for the client */
  556.  
  557.     ptcpPriv = (TCPPrivPtr)pPriv->devicePrivate;
  558.  
  559.     Bit_Clear(ptcpPriv->streamID, ClientsWithInputMask);
  560.  
  561.     if (ptcpPriv->needData) {
  562.     /*
  563.      * If previous buffer was exhausted and we haven't freed it, do so
  564.      * now. While we could just keep the buffer around, thereby adjusting
  565.      * it to the usual size the client will need, it could easily get
  566.      * out of hand if someone sends a good bit of image data, so
  567.      * we pay the price of copying rather than that of having buffers be
  568.      * too large.
  569.      */
  570.     if ((ptcpPriv->numBytes == 0) && (ptcpPriv->buffer != (Address)NULL)){
  571.         free((char *) ptcpPriv->buffer);
  572.         ptcpPriv->buffer = (Address)NULL;
  573.     }
  574.     need = -1;
  575.     if ((Ioc_NumReadable(ptcpPriv->streamID, &need) != SUCCESS) ||
  576.         (need <= 0)) {
  577.         /*
  578.          * If there are no bytes waiting, the other side has closed its
  579.          * connection (we could only have gotten here if the select
  580.          * returned readable, which implies that there are bytes to be
  581.          * read...), so we mark an error. (Also mark an error if
  582.          * we couldn't find how many bytes were available).
  583.          */
  584.         if (DBG(TCP)) {
  585.             ErrorF("Ioc_NumReadable: %d bytes readable\n", need);
  586.         }
  587.         *pStatus = -1;
  588.         return((char *)NULL);
  589.     }
  590.  
  591.     if (ptcpPriv->numBytes != 0) {
  592.         /*
  593.          * There were insufficient data in the buffer last time. We
  594.          * need to compress the buffer as much as possible to keep it
  595.          * from growing without bound (hard to do, but possible).
  596.          * If the space we've allocated already is big enough to
  597.          * hold the current data plus what's coming in now, we just copy
  598.          * the data in place, else we copy it to a new buffer and free
  599.          * the old one.
  600.          */
  601.         char  *newBuffer;
  602.         
  603.         if (Mem_Size(ptcpPriv->buffer) >= need + ptcpPriv->numBytes) {
  604.         newBuffer = ptcpPriv->buffer;
  605.         } else {
  606.         newBuffer = malloc(need + ptcpPriv->numBytes);
  607.         }
  608.         if (ptcpPriv->bufPtr != newBuffer) {
  609.         bcopy(ptcpPriv->bufPtr, newBuffer, ptcpPriv->numBytes);
  610.         }
  611.         if (newBuffer != ptcpPriv->buffer) {
  612.         free((char *) ptcpPriv->buffer);
  613.         ptcpPriv->buffer = newBuffer;
  614.         }
  615.     } else {
  616.         ptcpPriv->buffer = malloc(need);
  617.     }
  618.     /*
  619.      * Read whatever data are available from the socket to the end of the
  620.      * buffer. Any error (including FS_WOULD_BLOCK) causes the connection
  621.      * to be severed (we shouldn't block since we're reading what's there)
  622.      */
  623.     numRead = read(ptcpPriv->streamID,
  624.         ptcpPriv->buffer + ptcpPriv->numBytes, need);
  625.     if (numRead == -1) {
  626.         if (DBG(TCP)) {
  627.         Error("Reading TCP connection %d",
  628.               ptcpPriv->streamID);
  629.         }
  630.         *pStatus = -1;
  631.         return ((char *)NULL);
  632.     }
  633.     ptcpPriv->bufPtr = ptcpPriv->buffer;
  634.     ptcpPriv->numBytes += numRead;
  635.  
  636.     }
  637.     /*
  638.      * bufPtr now points to the current request for the client. Figure out how
  639.      * much data must be in the buffer for the request to be complete and store
  640.      * it in 'need'. If there isn't that much data, we have an incomplete
  641.      * request and need to read more data, so we set needData 1 and return
  642.      * a status of 0.
  643.      *
  644.      * If there is enough data, we update the various pointers and whatnot to
  645.      * reflect the taking of the request, then if there's still data in the
  646.      * buffer, note this client as having more input by setting the bit for the
  647.      * stream in the ClientsWithInputMask. The scheduler will exhaust this
  648.      * data before going to sleep again. While it is possible for a client to
  649.      * monopolize the server by cleverly sending incomplete data packets
  650.      * at just the right time, it seems unlikely that it could manage it.
  651.      */
  652.     if (ptcpPriv->numBytes < sizeof(xReq)) {
  653.     ptcpPriv->needData = 1;
  654.     *pStatus = 0;
  655.     SchedYield();
  656.     return ((char *)NULL);
  657.     }
  658.     need = request_length(ptcpPriv->bufPtr, ptcpPriv->client);
  659.     if (need > ptcpPriv->numBytes) {
  660.     ptcpPriv->needData = 1;
  661.     *pStatus = 0;
  662.     SchedYield();
  663.     return ((char *)NULL);
  664.     }
  665.     reqPtr = (xReq *)ptcpPriv->bufPtr;
  666.     ptcpPriv->bufPtr += need;
  667.     ptcpPriv->numBytes -= need;
  668.     *pStatus = need;
  669.     ptcpPriv->needData = 1;
  670.     
  671.     if (ptcpPriv->numBytes) {
  672.     if (ptcpPriv->numBytes >= sizeof(xReq)) {
  673.         need = request_length(ptcpPriv->bufPtr, ptcpPriv->client);
  674.         if (ptcpPriv->numBytes >= need) {
  675.         /*
  676.          * We only don't need data in the buffer if we have a
  677.          * complete request sitting there. In such a case, we mark
  678.          * the client as already having input and set needData 0.
  679.          */
  680.         Bit_Set(ptcpPriv->streamID, ClientsWithInputMask);
  681.         ptcpPriv->needData = 0;
  682.         }
  683.     }
  684.     }
  685.     if (ptcpPriv->needData) {
  686.     /*
  687.      * Once we run out of data in the request buffer, we have to wait
  688.      * for another select to return this stream's readiness.
  689.      */
  690.     SchedYield();
  691.     }
  692.     return ((char *)reqPtr);
  693. }
  694.  
  695. /*-
  696.  *-----------------------------------------------------------------------
  697.  *
  698.  * TCPWriteClient --
  699.  *    Write information to the client. We have a choice of making
  700.  *    two write calls or copying the data to longword-align it. For
  701.  *    now, just make the two system calls. We'll see which is worse...
  702.  *    We could use writev, but that's not restartable in case
  703.  *    of an interrupt.
  704.  *
  705.  * Results:
  706.  *    The number of bytes written.
  707.  *
  708.  * Side Effects:
  709.  *    Data are written to
  710.  *
  711.  *-----------------------------------------------------------------------
  712.  */
  713. static int
  714. TCPWriteClient (pPriv, numBytes, xRepPtr)
  715.     ClntPrivPtr      pPriv;
  716.     int              numBytes;
  717.     Address       xRepPtr;
  718. {
  719.     TCPPrivPtr      ptcpPriv;
  720.     int              pad = 0;
  721.     int              numPadBytes;
  722.  
  723.     ptcpPriv = (TCPPrivPtr)pPriv->devicePrivate;
  724.     numPadBytes = (4 - (numBytes & 3)) & 3;
  725.  
  726.     if (TCPConnIO(ptcpPriv->streamID, numBytes, xRepPtr, TCP_WRITE)!=0){
  727.     MarkClientException(ptcpPriv->client);
  728.     return(-1);
  729.     }
  730.     if (numPadBytes &&
  731.     (TCPConnIO(ptcpPriv->streamID, numPadBytes,&pad,TCP_WRITE)!=0)){
  732.     MarkClientException(ptcpPriv->client);
  733.     return(-1);
  734.     }
  735.     return (numBytes);
  736. }
  737. #endif TCPCONN
  738. @
  739.  
  740.  
  741. 1.6
  742. log
  743. @Include bit.h.
  744. @
  745. text
  746. @d19 1
  747. a19 1
  748. "$Header: tcp.c,v 1.5 88/09/09 09:00:04 ouster Exp $ SPRITE (Berkeley)";
  749. d95 1
  750. a95 1
  751.     inAddr.sin_port = htonl(X_TCP_PORT + displayNum);
  752. @
  753.  
  754.  
  755. 1.5
  756. log
  757. @Changes to compile with new C library.
  758. @
  759. text
  760. @d19 1
  761. a19 1
  762. "$Header: tcp.c,v 1.4 88/09/08 18:15:45 ouster Exp $ SPRITE (Berkeley)";
  763. d37 1
  764. @
  765.  
  766.  
  767. 1.4
  768. log
  769. @Intermediate check-in while converting to new C library.
  770. @
  771. text
  772. @d19 1
  773. a19 1
  774. "$Header: tcp.c,v 1.3 87/11/29 19:50:57 deboor Exp $ SPRITE (Berkeley)";
  775. d94 2
  776. a95 2
  777.     inAddr.sin_port = X_TCP_PORT + displayNum;
  778.     inAddr.sin_addr = (struct in_addr) INADDR_ANY;
  779. @
  780.  
  781.  
  782. 1.3
  783. log
  784. @Set to ignore SIG_PIPE. Added conditional debugging and some comments. Nuked
  785. some former debugging code
  786. @
  787. text
  788. @d19 1
  789. a19 1
  790. "$Header: tcp.c,v 1.2 87/11/01 20:40:52 deboor Exp $ SPRITE (Berkeley)";
  791. d24 9
  792. a35 1
  793. #include    "net.h"
  794. d37 2
  795. d41 1
  796. d52 1
  797. a52 1
  798.     Boolean          needData;     /* TRUE if need to read data */
  799. d89 1
  800. a89 1
  801.     Net_InetSocketAddr    inAddr;
  802. d91 1
  803. a91 1
  804.     Sig_Action          ignore;
  805. d93 3
  806. a95 3
  807.     (void) Cvt_AtoI(display, 10, &displayNum);
  808.     inAddr.port = X_TCP_PORT + displayNum;
  809.     inAddr.address = NET_INET_ANY_ADDR;
  810. d103 1
  811. a103 1
  812.     if (bind(TCP_Conn, &inAddr, sizeof(inAddr)) < 0) {
  813. d114 3
  814. a116 3
  815.     ignore.action = SIG_IGNORE_ACTION;
  816.     ignore.sigHoldMask = 0;
  817.     Sig_SetAction(SIG_PIPE, &ignore, (Sig_Action *)0);
  818. d126 2
  819. a127 1
  820.  *    A ReturnStatus indicating SUCCESS or failure.
  821. d141 4
  822. a144 5
  823.     SpriteTime      timeout;
  824.     int              *selMask;
  825.     int              numIO;
  826.     ReturnStatus  status;
  827.     int              timesBlocked;
  828. d150 1
  829. a150 1
  830.         status = Fs_Write(streamID, numBytes, bufPtr, &numIO);
  831. d152 1
  832. a152 1
  833.         status = Fs_Read(streamID, numBytes, bufPtr, &numIO);
  834. d154 1
  835. a154 1
  836.     if (status == SUCCESS) {
  837. d165 1
  838. a165 1
  839.         return (SUCCESS);
  840. d167 1
  841. a167 1
  842.     } else if (status == FS_WOULD_BLOCK) {
  843. d177 1
  844. a177 1
  845.         return (FS_WOULD_BLOCK);
  846. d179 3
  847. a181 3
  848.         
  849.         timeout.seconds = REASONABLE_TIME;
  850.         timeout.microseconds = 0;
  851. d184 5
  852. a188 5
  853.         status = Fs_Select(streamID + 1, &timeout,
  854.                    (ioType == TCP_READ ? selMask : 0),
  855.                    (ioType == TCP_WRITE ? selMask : 0),
  856.                    (int *)0, &numIO);
  857.         } while (status == GEN_ABORTED_BY_SIGNAL);
  858. d194 1
  859. a194 1
  860.         return (status);
  861. d207 1
  862. a207 1
  863.  *    TRUE if the connection is OK. FALSE otherwise.
  864. d210 1
  865. a210 1
  866.  *    *pSwapped is set TRUE if the client needs to be byte-swapped.
  867. d215 1
  868. a215 1
  869. static Boolean
  870. d219 1
  871. a219 1
  872.     Net_InetSocketAddr    *pInAddr;   /* Address of connected client */
  873. d226 1
  874. a226 1
  875.     if (TCPConnIO(conn, sizeof(xccp), &xccp, TCP_READ) != SUCCESS) {
  876. d231 1
  877. a231 1
  878.     return (FALSE);
  879. d235 1
  880. a235 1
  881.     *pSwapped = TRUE;
  882. d237 1
  883. a237 1
  884.     *pSwapped = FALSE;
  885. d243 1
  886. a243 1
  887.         return (FALSE);
  888. d248 1
  889. a248 1
  890.     return (FALSE);
  891. d255 1
  892. a255 1
  893.               TCP_READ) != SUCCESS) {
  894. d258 1
  895. a258 1
  896.             return (FALSE);
  897. d267 1
  898. a267 1
  899.               TCP_READ) != SUCCESS) {
  900. d270 1
  901. a270 1
  902.                 return (FALSE);
  903. d274 1
  904. a274 1
  905.     return (TRUE);
  906. d302 1
  907. a302 1
  908.     reasonLength = String_Length(reason);
  909. d321 1
  910. a321 1
  911.     String_Copy (reason, (char *)(packet+1));
  912. d351 1
  913. a351 1
  914.     Net_InetSocketAddr    inAddr;        /* Address of new client */
  915. d353 1
  916. a353 1
  917.     Boolean           swapped;    /* TRUE if client is byte-swapped */
  918. d373 1
  919. a373 1
  920.     Fs_Close(newID);
  921. d376 1
  922. a376 1
  923.     client = NextAvailableClient();
  924. d382 1
  925. a382 1
  926.     Fs_Close(newID);
  927. d385 1
  928. a385 1
  929.     pPriv = (ClntPrivPtr) Mem_Alloc(sizeof(ClntPrivRec));
  930. d392 1
  931. a392 1
  932.     ptcpPriv = (TCPPrivPtr)Mem_Alloc(sizeof(TCPPrivRec));
  933. d402 1
  934. a402 1
  935.     ptcpPriv->needData = TRUE;
  936. d451 1
  937. a451 1
  938.     Mem_Free(ptcpPriv->buffer);
  939. d466 1
  940. a466 1
  941.     Mem_Free((Address)ptcpPriv);
  942. d515 1
  943. a515 1
  944.         Mem_Free(ptcpPriv->buffer);
  945. d523 1
  946. a523 1
  947.          * connection (we could only have gotten here if the Fs_Select
  948. d550 1
  949. a550 1
  950.         newBuffer = Mem_Alloc(need + ptcpPriv->numBytes);
  951. d553 1
  952. a553 1
  953.         Byte_Copy (ptcpPriv->numBytes, ptcpPriv->bufPtr, newBuffer);
  954. d556 1
  955. a556 1
  956.         Mem_Free(ptcpPriv->buffer);
  957. d560 1
  958. a560 1
  959.         ptcpPriv->buffer = Mem_Alloc(need);
  960. d567 9
  961. a575 9
  962.     if (Fs_Read(ptcpPriv->streamID, need,
  963.             ptcpPriv->buffer + ptcpPriv->numBytes,
  964.             &numRead) != SUCCESS) {
  965.             if (DBG(TCP)) {
  966.                 Error("Reading TCP connection %d",
  967.                   ptcpPriv->streamID);
  968.             }
  969.             *pStatus = -1;
  970.             return ((char *)NULL);
  971. d585 1
  972. a585 1
  973.      * request and need to read more data, so we set needData TRUE and return
  974. d597 1
  975. a597 1
  976.     ptcpPriv->needData = TRUE;
  977. d604 1
  978. a604 1
  979.     ptcpPriv->needData = TRUE;
  980. d613 1
  981. a613 1
  982.     ptcpPriv->needData = TRUE;
  983. d622 1
  984. a622 1
  985.          * the client as already having input and set needData FALSE.
  986. d625 1
  987. a625 1
  988.         ptcpPriv->needData = FALSE;
  989. d632 1
  990. a632 1
  991.      * for another Fs_Select to return this stream's readiness.
  992. d646 1
  993. a646 1
  994.  *    We could use Fs_WriteVector, but that's not restartable in case
  995. d670 1
  996. a670 1
  997.     if (TCPConnIO(ptcpPriv->streamID, numBytes, xRepPtr, TCP_WRITE)!=SUCCESS){
  998. d675 1
  999. a675 1
  1000.     (TCPConnIO(ptcpPriv->streamID, numPadBytes,&pad,TCP_WRITE)!=SUCCESS)){
  1001. @
  1002.  
  1003.  
  1004. 1.2
  1005. log
  1006. @Added final touches to get TCPReadClient to work correctly
  1007. (Bit_Clear for ClientsWithInputMask).
  1008. @
  1009. text
  1010. @d19 1
  1011. a19 1
  1012. "$Header: tcp.c,v 1.1 87/11/01 20:23:36 deboor Exp $ SPRITE (Berkeley)";
  1013. d80 1
  1014. d102 4
  1015. d216 3
  1016. a218 1
  1017.     Error("Reading client prefix");
  1018. d335 2
  1019. a336 2
  1020.     ClientPtr      *pNewClients;
  1021.     int              *pNumNew;
  1022. d338 8
  1023. a345 8
  1024.     int                  newID;
  1025.     ClientPtr          client;
  1026.     Net_InetSocketAddr    inAddr;
  1027.     int                  addrLen;
  1028.     Boolean           swapped;
  1029.     ClntPrivPtr          pPriv;
  1030.     TCPPrivPtr          ptcpPriv;
  1031.     char              *reason;
  1032. d352 3
  1033. a354 1
  1034.     Error("accept");
  1035. d358 3
  1036. a360 1
  1037.     ErrorF("Unauthorized connection\n");
  1038. d367 3
  1039. a369 1
  1040.     ErrorF("No more clients!\n");
  1041. d404 4
  1042. a407 2
  1043.     ErrorF("New TCP connection: client %d (newID = %d)\n", client->index,
  1044.        newID);
  1045. a503 3
  1046. #ifdef notdef
  1047.         ErrorF("TCPReadClient: Freeing old buffer\n");
  1048. #endif
  1049. d509 1
  1050. a509 1
  1051.         (need == 0)) {
  1052. d517 3
  1053. a519 1
  1054.         ErrorF("Ioc_NumReadable: %d bytes readable\n", need);
  1055. a521 4
  1056.     } else {
  1057. #ifdef notdef
  1058.         ErrorF("Ioc_NumReadable: %d bytes readable\n", need);
  1059. #endif
  1060. d559 4
  1061. a562 1
  1062.             Error("Reading TCP connection %d", ptcpPriv->streamID);
  1063. a588 3
  1064. #ifdef notdef
  1065.     ErrorF("TCPReadClient: %d < sizeof(xReq)\n", ptcpPriv->numBytes);
  1066. #endif notdef
  1067. a595 3
  1068. #ifdef notdef
  1069.     ErrorF("TCPReadClient: need %d, have %d\n", need, ptcpPriv->numBytes);
  1070. #endif notdef
  1071. a601 3
  1072. #ifdef notdef
  1073.     ErrorF("TCPReadClient: read %d-byte request\n", need);
  1074. #endif
  1075. a612 4
  1076. #ifdef notdef
  1077.         ErrorF("TCPReadClient: %d-byte request still waiting\n",
  1078.                need);
  1079. #endif
  1080. a622 3
  1081. #ifdef notdef
  1082.     ErrorF("TCPReadClient: Yielding\n");
  1083. #endif
  1084. @
  1085.  
  1086.  
  1087. 1.1
  1088. log
  1089. @Initial revision
  1090. @
  1091. text
  1092. @d19 1
  1093. a19 1
  1094. "$Header$ SPRITE (Berkeley)";
  1095. d477 2
  1096. d576 3
  1097. d586 3
  1098. d623 3
  1099. @
  1100.